import Element.elem

abstract class Element {
  
  def contents: Array[String]
  
  def height: Int = contents.length
  
  def width: Int = if (height == 0) 0 else contents(0).length
  
  def above(that: Element): Element = {
      val this1 = this widen that.width
      val that1 = that widen this.width
		  elem(this1.contents ++ that1.contents)
  }
  
  def beside(that: Element): Element = {
    val this1 = this heighten that.height
    val that1 = that heighten this.height
    elem(
        for ( (line1, line2) <- this1.contents zip that1.contents) yield line1 + line2
        )
  }
  
  def widen(w: Int): Element = {
    if (w <= width) this
    else {
      val left = elem(' ', height, (w - width) / 2)
      val right = elem(' ', height, w - left.width - width)
      left beside this beside right
    }
  }
  
  def heighten(h: Int): Element = {
    if (h <= height) this
    else {
      val top = elem(' ', (h - height) / 2, width)
      var bot = elem(' ', h - top.height - height, width)
      top above this above bot
    }
  }
  
  override def toString = contents mkString "\n";
  
}

object Element {
  
  private class ArrayElement(val contents: Array[String]) extends Element
  
  private class LineElement(s: String) extends Element {
  
  def contents = Array(s)
  
  override def height = 1
  
  override def width = s.length
  }
  
  class UniformElement(
  val ch: Char,  
  override val height: Int,
  override val width: Int
  ) extends Element {
  
  val line = ch.toString * width
  val contents = Array.fill(height)(line)
//  val contents = new Array[String](height)
//  for (i <- 0 until contents.length) contents(i) = line
  }
  
  def elem(array: Array[String]): Element =
    new ArrayElement(array)
  
  def elem(str: String): Element = 
    new LineElement(str)
  
  def elem(ch: Char, height: Int, width: Int) = 
    new UniformElement(ch, height, width)
  
}